package com.deliveryservicesystem.app.conf;

import com.deliveryservicesystem.app.exceptions.OutputError;
import com.deliveryservicesystem.app.util.AppFileLoc;
import com.deliveryservicesystem.dataaccess.DatabaseConnection;
import com.deliveryservicesystem.service.ScriptRunner;
import java.io.*;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/**
 * File Name: InitDatabase.java
 * Version:
 * Description:
 * Package: com.deliveryservicesystem.test
 * Author: Lance
 * Date: Jun 19, 2012
 * Editor:
 */
public class InitDatabase
{

    private String scriptFilePath = AppFileLoc.SCRIPT_FILEPATH;
    private String databasePropertiesFilePath = AppFileLoc.DATABASE_PROPERTIES_FILEPATH;

    public InitDatabase()
    {
    }

    public void initDatabase()
    {
        try
        {
            runScript();
        }
        catch (SQLException ex)
        {
            OutputError.toLog(ex);
            OutputError.toUser(ex);
        }
    }

    private void runScript() throws SQLException
    {
        DatabaseConnection databaseConnsection = DatabaseConnection.getInstance();
        Connection connection = databaseConnsection.getConnection();
        ScriptRunner scriptRunner = new ScriptRunner(connection, false, false);
        scriptRunner.setDelimiter("/", false);
        Reader reader;
        try
        {
            scriptRunner.setLogWriter(new PrintWriter(new FileOutputStream("ScriptLog.txt", true)));
            scriptRunner.setErrorLogWriter(new PrintWriter(new FileOutputStream("ScriptErrorLog.txt", true)));
            reader = new FileReader(scriptFilePath);
            scriptRunner.runScript(reader);
        }
        catch (IOException ex)
        {
            OutputError.toLog(ex);
            OutputError.toUser(ex);
        }
    }

    public void createPersistenceUnit()
    {
        try
        {
            InputStream schemaIS = this.getClass().getClassLoader().getResourceAsStream("META-INF/persistence.xml");
            //get database credentials from dataBase.properties
            Properties dataBaseProperties = new Properties();
            dataBaseProperties.load(new FileInputStream(databasePropertiesFilePath));
            String userName = dataBaseProperties.getProperty("userName");
            String password = dataBaseProperties.getProperty("password");
            String databaseURL = dataBaseProperties.getProperty("dbUrl");
            String databaseDriver = dataBaseProperties.getProperty("jdbcDriver", "oracle.jdbc.OracleDriver");

            //Open persistence.xml
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(schemaIS);

            Node properties = doc.getElementsByTagName("properties").item(0);
            if (properties.getChildNodes().getLength() == 1)
            {
                // Create property url
                Element createElement = doc.createElement("property");
                createElement.setAttribute("name", "javax.persistence.jdbc.url");
                createElement.setAttribute("value", databaseURL);
                properties.appendChild(createElement);
                // Create property password
                createElement = doc.createElement("property");
                createElement.setAttribute("name", "javax.persistence.jdbc.password");
                createElement.setAttribute("value", password);
                properties.appendChild(createElement);
                // Create property driver
                createElement = doc.createElement("property");
                createElement.setAttribute("name", "javax.persistence.jdbc.driver");
                createElement.setAttribute("value", databaseDriver);
                properties.appendChild(createElement);
                // Create property user
                createElement = doc.createElement("property");
                createElement.setAttribute("name", "javax.persistence.jdbc.user");
                createElement.setAttribute("value", userName);
                properties.appendChild(createElement);
            }
            else
            {
                // Get and write property element 0
                Node property = doc.getElementsByTagName("property").item(0);
                NamedNodeMap attributes = property.getAttributes();
                Node namedItem = attributes.getNamedItem("value");
                namedItem.setTextContent(databaseURL);
                // Get and write property element 1
                property = doc.getElementsByTagName("property").item(1);
                attributes = property.getAttributes();
                namedItem = attributes.getNamedItem("value");
                namedItem.setTextContent(password);
                // Get and write property element 2
                property = doc.getElementsByTagName("property").item(2);
                attributes = property.getAttributes();
                namedItem = attributes.getNamedItem("value");
                namedItem.setTextContent(databaseDriver);
                // Get and write property element 3
                property = doc.getElementsByTagName("property").item(3);
                attributes = property.getAttributes();
                namedItem = attributes.getNamedItem("value");
                namedItem.setTextContent(userName);
            }

            // write the content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();

            DOMSource source = new DOMSource(doc);
            URL resource = this.getClass().getClassLoader().getResource("META-INF/persistence.xml");
            String file = resource.getPath();
            StreamResult result = new StreamResult(new File(file));
            transformer.transform(source, result);
        }
        catch (TransformerException | SAXException | IOException | ParserConfigurationException ex)
        {
            OutputError.toLog(ex);
            OutputError.toUser(ex);
        }
    }
}